"""
债券买入持有策略
"""
from typing import Dict, List, Optional
from datetime import datetime
import pandas as pd
import numpy as np
from loguru import logger

from strategy.base import Strategy
from engine.event import EventType, Event, OrderEvent, OrderType, CashFlowType
from engine.assets import AssetType

class BondBuyHoldStrategy(Strategy):
    """
    债券买入持有策略
    
    策略逻辑：
    1. 在回测开始时买入目标债券
    2. 持有至到期
    3. 可以设置是否使用杠杆（通过回购融资）
    """
    
    def __init__(self, name: str, leverage: float = 1.0):
        """
        初始化策略
        
        参数:
            name: 策略名称
            leverage: 杠杆倍数，默认为1（不使用杠杆）
        """
        super().__init__(name=name)
        self.leverage = leverage
        self.has_traded = False  # 用于标记是否已经交易
        self.has_sold = False
        logger.info(f"初始化策略: {self.name}, 杠杆={leverage}")
    
    def initialize(self) -> None:
        """初始化策略"""
        pass
    
    def on_data(self,data):
        """
        处理市场数据
        """        

        # 如果已经交易过，不再重复交易
        if self.has_sold:
            return
        
        # 获取当前时间和市场数据
        self.current_date =  self.engine.current_time
        market_data = data

        
        # 获取可用资金
        available_cash = self.engine.position.current_cash

        for symbol,position in self.engine.position.positions.items():
            # 持仓时间大于270天则卖出
            current_price = market_data[symbol].loc[self.current_date, 'close']
            
            if position.holding_period > 270 and position.asset_type == AssetType.BOND:
                print(f'{self.current_date},holding_period:',position.holding_period)
                quantity = position.quantity
                direction = -1
                self.place_order(symbol=symbol,quantity=quantity,
                                    order_type=OrderType.MARKET,direction=direction,
                                    asset_type=AssetType.BOND)


                available_cash -= quantity * current_price * direction
                logger.info(f"下单卖出债券: {symbol}, 最大可卖金额={quantity}, \
                        卖出数量={quantity}, 价格={current_price:.4f},卖出后剩余现金={available_cash:.2f}")
                self.has_sold = True
                
        if available_cash <= 0:
            return
        # 遍历所有资产
        if not self.has_traded:
            for symbol, data in market_data.items():
                # 只处理债券资产
                asset = self.engine.assets.get(symbol)
                if asset.asset_type != AssetType.BOND:
                    continue
                
                # 获取当前价格(这里需要用作交易，所以使用债券全价)
            
                current_price = data.loc[self.current_date, 'close'] + asset.accrued_interest(self.current_date, 1)
                
                # 计算可买金额（考虑杠杆）
                max_available_cash = available_cash * self.leverage
                # 计算可买数量
                quantity = int(max_available_cash / current_price)
                
                if quantity <= 0:
                    continue
                
                # 如果使用杠杆，先进行回购融资
                if self.leverage > 1:
                    repo_amount = available_cash * (self.leverage - 1)
                    for repo_symbol, repo_data in market_data.items():
                        repo_asset = self.engine.assets.get(repo_symbol)
                        if repo_asset.asset_type != AssetType.REPO:
                            continue
                        
                        # 执行回购融资
                        self.place_order(repo_symbol,repo_amount,OrderType.MARKET,
                        None,-1,AssetType.REPO)
                    
                        break
                
                # 买入债券
                direction = 1
                self.place_order(symbol,quantity,OrderType.MARKET,
                None,direction,AssetType.BOND)
                available_cash -= quantity * current_price * direction
                logger.info(f"下单买入债券: {symbol}, 最大可买金额={max_available_cash}, \
                            买入数量={quantity}, 价格={current_price:.4f},买入后剩余现金={available_cash:.2f}")
                
                # 标记已交易
                self.has_traded = True
                break  # 只买入一只债券
    def on_cashflow(self,event ) -> None:
        """
        处理现金流事件
        """

        if event.cashflow_type == CashFlowType.PRINCIPAL and \
            event.asset_type == AssetType.REPO:
            # logger.info(f"回购到期：{event}")
            if event.amount <= 0: # 到期资金流出，则表示到期标的为正回购
                direction = -1
            else: # 到期资金流入，则表示到期标的为负回购
                direction = 1
            # 如果回购到期，执行回购融资
            quantity = abs(event.amount)
            self.place_order('repo_2',quantity,OrderType.MARKET,None,direction,AssetType.REPO)
            available_cash = self.engine.position.current_cash - abs(event.amount) * direction 
            logger.info(f"下单更新回购: {event.symbol},\
                        买入数量={quantity},,买入后剩余现金={available_cash:.2f}")

